﻿#include "XNetSDKTest.h"
#include "XNetSDKSyn.h"

XSDK_HANDLE g_hDevice = 0;

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include "H265Decoder.hpp"

int CALLBACK Main_MessageCallBack(XSDK_HANDLE hDevice, int nMsgId, int nParam1, int nParam2, int nParam3, const char *szString, void *pObject, int nSeq, void *pUserData);


H265Decoder testDecoder;


int CALLBACK Test_MediaCallBack(XSDK_HANDLE hMedia, const unsigned char *pData, int nDataLen, int nDataType, 
															void *pDataInfo, int nDataInfoSize, void *pUserData)
{
	// EXSDK_DATA_FORMATE_FRAME带有帧信息的码流数据  pData：码流数据  nDataLen码流数据长度 pDataInfo：帧信息
 	if (EXSDK_DATA_FORMATE_FRAME == nDataType && nDataInfoSize > 0)
	{
		SXSDK_FRAME_INFO *pFrame = (SXSDK_FRAME_INFO *)pDataInfo;
		// printf("Media[hMedia:%ld][Len:%d][Type:%d/%d][nEncodeType:%d]\r\n", 
		// hMedia, nDataLen, pFrame->nType, pFrame->nSubType, pFrame->nEncodeType);
		testDecoder.AddData(pData, nDataLen);
		char * pOutData = NULL;
		int OutSize = 0;
		if(!testDecoder.GetData(pOutData, OutSize))
		{
			printf("ERROR DECODER\n");
		}else{
			cv::Mat scrImg(1080*1.5, 1920, CV_8UC1);
			memcpy(scrImg.data,pOutData, OutSize * sizeof(unsigned char));
			cv::Mat bgrImg;
			cv::cvtColor(scrImg, bgrImg, CV_YUV2BGR_I420);
			cv::Mat shrink;
        	resize(bgrImg, shrink, cv::Size(bgrImg.cols/4, bgrImg.rows/4), 0, 0, cv::INTER_AREA);
			cv::namedWindow("bgrImg");
			cv::imshow("bgrImg", shrink);
			cv::waitKey(1);
		}

	}
	else if (EXSDK_DATA_MEDIA_ON_PLAY_STATE == nDataType)
	{
		printf("EXSDK_DATA_MEDIA_ON_PLAY_STATE[%d][%d]\r\n", hMedia, nDataLen);
	}
	else if (ESXSDK_MEDIA_START_REAL_PLAY == nDataType)
	{
		printf("OnRealPlayResult[%d][%s]\r\n", hMedia, nDataLen >= 0 ? "Success" : "Failed");
	}
	else 
	{
		printf("Media[hMedia:%ld][Len:%d][Type:%d]\r\n", hMedia, nDataLen, nDataType);
	}
	return 0;
}

int TestMediaRealPlay()
{
	printf("%s\r\n", __FUNCTION__);

	XSDK_HANDLE hPlayer = 0;
	bool bPause = false;
	int nSpeed = 0;

	char c = 0;
	while((c = getchar()) != 'q')
	{
		switch(c)
		{
		case 's':
			{
				if (hPlayer)
				{
					XSDK_MediaStop(hPlayer);
					hPlayer = 0;
				}

				SXMediaRealPlayReq param = {0};
				param.nChannel = 0;
				param.nStreamType = 0;
				param.nRequestType = EXSDK_DATA_FORMATE_FRAME;
				param.pMediaCallback = Test_MediaCallBack;
				hPlayer = XSDK_MediaRealPlay(g_hDevice, &param);
				if(hPlayer > 0){
					printf("success read\n");
				}
				bPause = false;
				nSpeed = 0;
			}
			break;
		case 't':
			{
				if (hPlayer)
				{
					XSDK_MediaStop(hPlayer);
					hPlayer = 0;
				}
			}
			break;
		}
	}

	if (hPlayer)
	{
		XSDK_MediaStop(hPlayer);
		hPlayer = 0;
	}
	return 0;
}


int main(int argc, char *argv[])
{
	testDecoder.Init();
	SXSDKInitParam initParam = {0};
	initParam.pMsgCallBack = Main_MessageCallBack;	///注册接收数据回调函数
	XSDK_Init(&initParam);							///初始化
	XSDK_SetSDKIntAttr(1024, 0);
	
	const char *szDevID = "192.168.1.10";			///设备IP，主动注册模式时填服务器地址
	int nDevPort = 34567;
	const char *szUser = "admin";
	const char *szPwd = "";
	if (true && argc > 4)
	{
		szDevID = argv[1];
		nDevPort = atoi(argv[2]);
		szUser = argv[3];
		szPwd = argv[4];
	}

	SXSDKLoginParam devParam = {0};
	strcpy(devParam.sDevId, szDevID);
	devParam.nDevPort = nDevPort;
	strcpy(devParam.sUserName, szUser);
	strcpy(devParam.sPassword, szPwd);

	g_hDevice = XSDK_DevLoginSyn(&devParam, 10000);	///同步模式登录设备，大于0对应句柄，其它失败对应错误码


	TestMediaRealPlay();


	if (g_hDasServer)
	{
		XSDK_StopDASServer(g_hDasServer);
		g_hDasServer = 0;
	}

	XSDK_DevLogout(g_hDevice);
	XSDK_UnInit();

	return 0;
}


void OnDASServerStart(XSDK_HANDLE hServer, int nResult)
{
	printf("OnDASServerStart-->%d:%d\r\n", hServer, nResult);
}

int TestDevSearch()
{
	printf("%s\r\n", __FUNCTION__);
	char c = 0;
	int nTimeOut = 4000;
	while((c = getchar()) != 'q')
	{
		switch(c)
		{
		case 'a':
			{
				XSDK_SearchDevices(nTimeOut);
			}
			break;
		case 'b':
			{
				int nMaxCount = 64;
				int nActualCount = 0;
				SXSDK_CONFIG_NET_COMMON* pRet = new SXSDK_CONFIG_NET_COMMON[nMaxCount];
				memset(pRet, 0, sizeof(SXSDK_CONFIG_NET_COMMON) * nMaxCount);
				nActualCount = XSDK_SearchDevicesSyn(pRet, nMaxCount);
				printf("nCount:%d\r\n", nActualCount);
				if (pRet)
				{
					delete[]pRet;
					pRet = NULL;
				}
			}
			break;
		}
	}
	
	return 0;
}

bool GetMacByGetAdaptersInfo(char *pMacRet)
{
	bool ret = false;
#ifdef WIN32
	ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
	PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
	if(pAdapterInfo == NULL)
	{
		return false;
	}

	if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) 
	{
		free(pAdapterInfo);
		pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
		if (pAdapterInfo == NULL) 
		{
			return false;
		}
	}

	if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR)
	{
		for(PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next)
		{
			char acMAC[32] = {0};
			sprintf(acMAC, "%02X:%02X:%02X:%02X:%02X:%02X",
				int (pAdapter->Address[0]),
				int (pAdapter->Address[1]),
				int (pAdapter->Address[2]),
				int (pAdapter->Address[3]),
				int (pAdapter->Address[4]),
				int (pAdapter->Address[5]));
			strcpy(pMacRet, acMAC);
			ret = true;
			break;
		}
	}

	free(pAdapterInfo);
#else     
	int sock_mac = socket( AF_INET, SOCK_STREAM, 0 );  
	if( sock_mac == -1)  
	{  
		perror("create socket falise...mac/n");  
		return false;  
	}  

	struct ifreq ifr_mac;
	memset(&ifr_mac,0,sizeof(ifr_mac));     
	strncpy(ifr_mac.ifr_name, "eth0", sizeof(ifr_mac.ifr_name)-1);     

	if( (ioctl( sock_mac, SIOCGIFHWADDR, &ifr_mac)) < 0)  
	{  
		printf("mac ioctl error/n");  
		return false;  
	}  

	char acMAC[32] = {0};
	sprintf(acMAC,"%02X:%02X:%02X:%02X:%02X:%02X",  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[0],  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[1],  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[2],  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[3],  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[4],  
		(unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]);  

	strcpy(pMacRet, acMAC);
	ret = true;
	close(sock_mac);  
#endif

	return ret;
}

void OnDevSearchResult(int nResult, SXSDK_CONFIG_NET_COMMON *pDevs, int nCount)
{
	printf("OnDevSearchResult[SearchResutl:%d][DeviceCount:%d]\r\n", nResult, nCount);
	for (int i = 0; i < nCount; i++)
	{
		printf("[%d][SN:%s][IP:%d.%d.%d.%d][Port:%d]\r\n", i, pDevs[i].sSn, 
			pDevs[i].HostIP.c[0], pDevs[i].HostIP.c[1], pDevs[i].HostIP.c[2], pDevs[i].HostIP.c[3],
			pDevs[i].TCPPort);
	}

	bool bModyfyIP = false;
	if (bModyfyIP)
	{
		char localMac[64] = {0};
		bool bRet = GetMacByGetAdaptersInfo(localMac);

		if(!bRet)
		{
			printf("Get LocalMac Fail\r\n");
			return;
		}

		signed char newEncryptPsw[512];
		memset(newEncryptPsw, 0, 512);
		XSDK_EncryptPassword((const char*)"", newEncryptPsw, 512);

		if(pDevs != NULL)
		{
			char ip[16] = {0};
			char gateway[16] = {0};
			char submask[16] = {0};
			sprintf(ip, "%d.%d.%d.%d", pDevs[0].HostIP.c[0], pDevs[0].HostIP.c[1], pDevs[0].HostIP.c[2], pDevs[0].HostIP.c[3]);
			sprintf(gateway, "%d.%d.%d.%d", pDevs[0].Gateway.c[0], pDevs[0].Gateway.c[1], pDevs[0].Gateway.c[2], pDevs[0].Gateway.c[3]);
			sprintf(submask, "%d.%d.%d.%d", pDevs[0].Submask.c[0], pDevs[0].Submask.c[1], pDevs[0].Submask.c[2], pDevs[0].Submask.c[3]);

			strcpy(ip, "10.10.88.219");

			SXSDK_CONFIG_NET_COMMON_V2 devInfo;
			memset(&devInfo, 0, sizeof(SXSDK_CONFIG_NET_COMMON_V2));

			devInfo.HostIP.l = inet_addr(ip);
			devInfo.Gateway.l = inet_addr(gateway);
			devInfo.Submask.l = inet_addr(submask);
			strcpy(devInfo.HostName, pDevs[0].HostName);
			devInfo.HttpPort = pDevs[0].HttpPort;
			strcpy(devInfo.LocalMac, localMac);
			devInfo.MaxBps = pDevs[0].MaxBps;
			devInfo.MaxConn = pDevs[0].MaxConn;
			devInfo.MonMode = 0;
			devInfo.nPasswordType = 1;
			strcpy(devInfo.Password, (const char*)newEncryptPsw);
			strcpy(devInfo.sMac, pDevs[0].sMac);
			devInfo.SSLPort = pDevs[0].SSLPort;
			devInfo.TCPPort = pDevs[0].TCPPort;
			devInfo.TransferPlan = pDevs[0].TransferPlan;
			devInfo.UDPPort = pDevs[0].UDPPort;
			strcpy(devInfo.UserName, "admin");

			XSDK_ModifyDevIP((const char*)&devInfo, sizeof(SXSDK_CONFIG_NET_COMMON_V2), 5000);
		}
	}
}

void OnDASDeviceReg(XSDK_HANDLE hDevice, SXSDKDASDeviceInfo *pDASInfo)
{
	// hDevice---等同于XSDK_DevLoginSyn/XSDK_DevLogin的返回值
	printf("OnDASDeviceReg-->\r\nIP:%s\r\nPort:%d\r\nDeiveID:%s\r\nUserName:%s\r\nPassword:%s\r\nChannelNum:%d\r\nEncryptyType:%s\r\n",
		pDASInfo->sDevIP, pDASInfo->nDevPort, pDASInfo->sDevId, pDASInfo->sUserName, pDASInfo->sPassword, pDASInfo->nChannelNum, pDASInfo->sEncryptType);
}
int CALLBACK Main_MessageCallBack(XSDK_HANDLE hDevice, int nMsgId, int nParam1, int nParam2, int nParam3, const char *szString, void *pObject, int nSeq, void *pUserData)
{
	//根据信息ID判断对应功能
	switch(nMsgId)
	{
		//返回异步登录接口登录句柄
	case ESXSDK_DEV_LOGIN:
		{
			printf("ESXSDK_DEV_LOGIN_Ret[%d]\r\n", nParam1);
			if (nParam1 == EXSDK_ER_UserOrPassword)
			{
				XSDK_DevLogout(hDevice);
			}

			if (nParam1 < 0)
			{
				printf("ESXSDK_DEV_LOGIN__Error\r\n");
			}
		}
		break;
		//返回设备连接状态
	case ESXSDK_ON_DEV_STATE:
		{
			//判断登录状态还是断线状态
			printf("ESXSDK_ON_DEV_STATE[%s]\r\n", nParam1 == 6 ? "ESTATE_DEV_Logined" : "ESTATE_DEV_NetDisConnect");
		}
		break;
		//返回搜索当前局域网设备信息
	case ESXSDK_ON_SEARCH_DEVICES:
		{
			OnDevSearchResult(nParam1, (SXSDK_CONFIG_NET_COMMON *)pObject, nParam2);
		}
		break;

		//返回主动注册功能是否成功开启
	case ESXSDK_ON_DAS_SERVER_START:
		{
			OnDASServerStart(hDevice, nParam1);
		}
		break;
		//返回主动注册模式下设备连接后的登录句柄
	case ESXSDK_ON_DAS_DEVICE_REGIST:
		{

			OnDASDeviceReg(hDevice, (SXSDKDASDeviceInfo *)pObject);
		}
		break;

	default:
		printf("[Dev:%ld][MSG:%d][Ret:%d][Param2:%d][Param3:%d][szParam:%s][Seq:%d]\r\n", hDevice, nMsgId, nParam1, nParam2, nParam3, szString == NULL ? "" : szString, nSeq);
		break;
	}

	return 0;
}
